﻿#region Copyright Notice
// 
// 
//  
//  Copyright (c) 2009-2011 Anindya Chatterjee
//  
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//  
//      http://www.apache.org/licenses/LICENSE-2.0
//  
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// 
// 
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using AbstractClass;
using AbstractClass.Collections;
using AbstractClass.Collections.Generic;
using AbstractClass.Extensions;
using NUnit.Framework;

namespace QuasarTest.Core
{
    [TestFixture]
    public class MatrixTest
    {
        #region Setup/Teardown

        [SetUp]
        public void Init()
        {
            _matrix = new Matrix<int>(3, 3);
            _doubleMatrix = new DoubleMatrix(3, 3);
            _booleanMatrix = new BooleanMatrix(3, 3);
            _complexMatrix = new ComplexMatrix(3, 3);

            PopulateMatrices();
        }

        #endregion

        private Matrix<int> _matrix;
        private DoubleMatrix _doubleMatrix;
        private BooleanMatrix _booleanMatrix;
        private ComplexMatrix _complexMatrix;

        private void PopulateMatrices()
        {
            var random = new Random();
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    _matrix[i, j] = random.Next();
                    _doubleMatrix[i, j] = random.NextDouble();
                    _booleanMatrix[i, j] = random.Next<Boolean>();
                    _complexMatrix[i, j] = new ComplexNumber(random.NextDouble(), random.NextDouble());
                }
            }
        }

        [Test]
        public void TestBooleanMatrix()
        {
            BooleanMatrix identity = BooleanMatrix.Identity(3);
            Assert.IsTrue(identity.GetDiagonal().All(x => x));
            Assert.AreEqual(identity * _booleanMatrix, _booleanMatrix);

            BooleanMatrix meet1 = BooleanMatrix.Meet(identity, _booleanMatrix);
            BooleanMatrix meet2 = BooleanMatrix.Meet(_booleanMatrix, false);

            BooleanMatrix join1 = BooleanMatrix.Join(identity, _booleanMatrix);
            BooleanMatrix join2 = BooleanMatrix.Join(_booleanMatrix, false);
        }

        [Test]
        public void TestComplexMatrix()
        {
            ComplexMatrix identity = ComplexMatrix.Identity(3);
            Assert.IsTrue(identity.GetDiagonal().All(x => x.Equals(ComplexNumber.One)));

            ComplexMatrix result = identity - _complexMatrix;
            Assert.AreEqual(result + _complexMatrix, identity);
        }

        [Test]
        public void TestDoubleMatrix()
        {
            IEnumerable<double> data = Iterable.Generate(1.2d, 2.5d, 9);
            var matrix = new DoubleMatrix(3, 3);
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    matrix[i, j] = data.ElementAt(i + j * 3);
                }
            }
            double norm1 = matrix.GetNorm1();
            double norm2 = matrix.GetNorm2();
            double normInf = matrix.GetNormInfinity();

            Assert.AreEqual(Math.Round(norm1, 2), 41.1d);
            Assert.AreEqual(Math.Round(norm2, 2), 38.78d);
            Assert.AreEqual(Math.Round(normInf, 2), 56.1d);

            DoubleMatrix result = _doubleMatrix + matrix;

            Assert.AreEqual((result - _doubleMatrix).ToArray(), matrix.ToArray());
        }

        [Test]
        public void TestGenericMatrix()
        {
            Assert.AreEqual(_matrix.Count, 9);
            Assert.AreEqual(_matrix.RowCount, _matrix.ColumnCount);

            Matrix<int> identityMatrix = Matrix<int>.Create(3, 3, 1);
            Assert.IsTrue(identityMatrix.All(x => x == 1));

            var matrix = new Matrix<int>(3, 3);
            matrix[0, 0] = -2;
            matrix[0, 1] = 2;
            matrix[0, 2] = -3;
            matrix[1, 0] = -1;
            matrix[1, 1] = 1;
            matrix[1, 2] = 3;
            matrix[2, 0] = 2;
            matrix[2, 1] = 0;
            matrix[2, 2] = -1;
            Assert.AreEqual(matrix.Trace(), -2);

            Matrix<int> trans = _matrix.Transpose();
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    Assert.AreEqual(_matrix[i, j], trans[j, i]);
                }
            }
        }

        [Test]
        public void TestTrace()
        {
        }
    }
}